﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;

namespace Efm.Progress
{

    public class PausedEventArgs : EventArgs
    {
        public bool IsPaused { get; internal set; }
    }

    public class ReportEventArgs : EventArgs
    {
        public double[] Value { get; internal set; }
    }

    public class ProgressBox
    {
        #region Event

        public delegate void CancelledEventHandler(object sender, EventArgs e);
        public event CancelledEventHandler Cancelled;
        protected virtual void OnCancelled()
        {
            IsCancelled = true;
            var handler = Cancelled;
            if (handler != null) handler(this, EventArgs.Empty);
            if (_window != null) _window.Close();
        }

        public delegate void PausedEventHandler(object sender, PausedEventArgs e);
        public event PausedEventHandler Paused;
        protected virtual void OnPaused()
        {
            var handler = Paused;
            if (handler != null) handler(this, new PausedEventArgs { IsPaused = IsPaused });
            if (_win != null) _win.SetTextButton();
        }

        public delegate void WorkEventHandler(object sender, EventArgs e);
        public event WorkEventHandler Work;
        protected virtual void OnWork()
        {
            var handler = Work;
            if (handler != null) handler(this, EventArgs.Empty);
            IsCompleted = true;
            if (_window != null) _window.Close();
        }

        public delegate void ReportProgressEventHandler(object sender, ReportEventArgs e);
        public event ReportProgressEventHandler Report;
        protected virtual void OnReport(params double[] value)
        {
            var handler = Report;
            if (handler != null) handler(this, new ReportEventArgs{Value = value});
        }

        #endregion

        #region Props and Filds

        private Window _window;
        private WinProgress _win;
        private DispatcherTimer _timer;
        private int _count;
        private bool _isPaused;
        private string _title;
        private string _text;
        

        public bool ShowWindow { get; set; }
        public bool ShowCancelButton { get; set; }
        public bool ShowPauseButton { get; set; }
        public bool CanMinimizeWindow { get; set; }



        public string Title
        {
            get { return _title; }
            set
            {
                _title = value;
                if (_window != null) _window.Title = value;
            }
        }
        public string Text
        {
            get { return _text; }
            set
            {
                _text = value;
                if (_win != null) _win.ContentText.Text = value;
            }
        }

        public bool IsCompleted { get; protected set; }
        public bool IsCancelled { get; protected set; }
        public bool IsPaused
        {
            get { return _isPaused; }
            protected set 
            { 
                _isPaused = value;
                OnPaused();
            }
        }

        public ProgressBar[] ProgressBars { get; protected set; }
        public int Count
        {
            get { return _count; }
            protected set
            {
                _count = value;
                ProgressBars = new ProgressBar[Count];
                for (var i = 0; i < Count; i++)
                {
                    ProgressBars[i] = new ProgressBar { Height = 20, Margin = new Thickness(0, 5, 0, 5) };
                }
            }
        }

        public ProgressBar this[int index]
        {
            get { return ProgressBars[index]; }
        }


        #endregion

        #region Method
        public ProgressBox(int countProgressBar = 1)
        {
            Count =  countProgressBar;
        }

        public void Start()
        {
            if (ShowWindow)
            {
                _win = new WinProgress(this);
                _win.All.SizeChanged += _win_SizeChanged;
                _window = new Window
                    {
                        Content = _win,
                        WindowStartupLocation = WindowStartupLocation.CenterScreen,
                        ResizeMode = ResizeMode.CanMinimize,
                        MinHeight = 40,
                        MinWidth = 400,
                        MaxHeight = SystemParameters.WorkArea.Height - 10,
                        MaxWidth = SystemParameters.WorkArea.Width - 50,
                        Width = 400,
                        Height = SystemParameters.WorkArea.Height - 10
                    };
                _window.Loaded += _window_Loaded;
                _window.Closed += _window_Closed;
                _window.ShowDialog();
            }
            else
                OnWork();

            
        }

        public void ReportProgress(params double[] values)
        {
            OnReport(values);
        }
        
        public void Cancel()
        {
            OnCancelled();
        }

        public void Pause()
        {
            IsPaused = !IsPaused;
        }

        private void dispatcherTimer_Tick(object sender, EventArgs e)
        {
            _timer.Stop();
            _window.Top = (SystemParameters.WorkArea.Height - _window.Height) / 2;
            _window.Left = (SystemParameters.WorkArea.Width - _window.Width) / 2;
            OnWork();
        }

        private void _window_Loaded(object sender, RoutedEventArgs e)
        {
            _window.Title = Title;
            _timer = new DispatcherTimer(TimeSpan.Zero, DispatcherPriority.ApplicationIdle, dispatcherTimer_Tick,
                                         Application.Current.Dispatcher);
        }

        private void _win_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            _window.Height = e.NewSize.Height + 42;
        }

        private void _window_Closed(object sender, EventArgs e)
        {
            if (!IsCompleted && !IsCancelled)
            {
                OnCancelled();
            }
        }

        #endregion
    }

    
}
